package net.wenku8.reader.service

import android.annotation.SuppressLint
import android.content.ContentValues
import android.content.Context
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Build
import android.provider.MediaStore
import android.provider.OpenableColumns
import android.util.Log
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.graphics.painter.BitmapPainter
import net.wenku8.reader.util.deleteFile
import net.wenku8.reader.util.getFileCharset
import net.wenku8.reader.util.mkParentDirs
import net.wenku8.reader.util.readAsByte
import net.wenku8.reader.util.writeStream
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.nio.charset.Charset


class FileService {

    companion object {

        @SuppressLint("StaticFieldLeak")
        lateinit var context : Context

        private fun getInnerFile(fileName : String) : File{
            return File(context.filesDir, fileName)
        }

        @SuppressLint("Recycle", "Range")
        fun getFileName(uri : Uri) : String?{
            try {
                val cursor = context.contentResolver.query(uri, null, null, null, null)
                cursor.use {
                    if (cursor != null && cursor.moveToFirst()) {
                        return cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME))
                    }
                }
            } catch (e: Exception) {
                Log.e("", "getFileName:", e)
            }
            return null
        }

        fun copyFile(fromUri : Uri, targetFile : String) : Boolean{
            try {
                val file = getInnerFile(targetFile)
                mkParentDirs(file)
                context.contentResolver.openInputStream(fromUri)?.let {
                    writeStream(it, FileOutputStream(file))
                }
            } catch (e: Exception) {
                Log.e("", "", e)
                return false
            }
            return true
        }

        @SuppressLint("Recycle")
        fun readAsString(fileName : String): String?{
            try {
                val file = getInnerFile(fileName)
                if (!file.exists()){
                    return null
                }
                val charset = getFileCharset(file)
                return FileInputStream(file).bufferedReader(Charset.forName(charset)).readText()
            } catch (e: Exception) {
                Log.e("", "", e)
            }
            return null
        }

        @SuppressLint("Recycle")
        fun readAsLine(fileName : String): List<String>?{
            try {
                val file = getInnerFile(fileName)
                if (!file.exists()){
                    return null
                }
                val charset = getFileCharset(file)
                return FileInputStream(file).bufferedReader(Charset.forName(charset)).readLines()
            } catch (e: Exception) {
                Log.e("", "", e)
            }
            return null
        }

        fun readFolder(folderName : String): List<String>{
            val list = ArrayList<String>()
            try {

                val file = getInnerFile(folderName)
                if (!file.exists()){
                    return list
                }
                if(file.isFile){
                    list.add(readAsString(folderName)?:"")
                }else{
                    file.list()?.forEach { subFile ->
                        list.add(readAsString("$folderName/$subFile")?:"")
                    }
                }
            } catch (e: Exception) {
                Log.e("", "", e)
            }
            return list
        }


        fun writeFile(fileName : String, data : String) {
            writeFile(fileName, data.toByteArray())
        }

        fun writeFile(fileName : String, data : ByteArray) {
            try {
                val file = getInnerFile(fileName)
                mkParentDirs(file)
                FileOutputStream(file, false).write(data)
            } catch (e: Exception) {
                Log.e("", "", e)
            }
        }

        @SuppressLint("NewApi")
        fun writeDownloadFile(fileName : String, data : ByteArray, folder : String? = null, mimeType : String = "image/jpeg") {
            try {
                val resolver = context.contentResolver
                // 创建一个 ContentValues 对象，包含文件的元数据
                if (folder != null){

                }
                val contentValues = ContentValues().apply {
                    put(MediaStore.Downloads.DISPLAY_NAME, fileName)
                    put(MediaStore.Downloads.MIME_TYPE, mimeType)
                    put(MediaStore.Downloads.IS_PENDING, 1)  // 标记为正在处理
                }
                // 插入新的文件到 MediaStore.Downloads
                val uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                    resolver.insert(MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL), contentValues)
                } else {
                    resolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues)
                }
                uri?.let {
                    // 打开输出流并写入图片内容
                    resolver.openOutputStream(it)?.use { outputStream ->
                        outputStream.write(data)
                    }
                    // 更新文件状态为完成
                    contentValues.clear()
                    contentValues.put(MediaStore.Downloads.IS_PENDING, 0)
                    resolver.update(it, contentValues, null, null)
                }
            } catch (e: Exception) {
                Log.e("", "", e)
            }
        }

        fun writeDownloadFile(fromFile : String, targetFile : String) : Boolean{
            try {
                val bytes = readAsByte(getInnerFile(fromFile))
                writeDownloadFile(targetFile, bytes!!)
            } catch (e: Exception) {
                Log.e("", "", e)
                return false
            }
            return true
        }


        fun deleteFile(fileName : String) {
            try {
                val file = getInnerFile(fileName)
                deleteFile(file)
            } catch (e: Exception) {
                Log.e("", "", e)
            }
        }

        fun exists(fileName : String) : Boolean {
            val file = getInnerFile(fileName)
            return file.exists()
        }

        fun imageAsPainter(fileName : String) : BitmapPainter? {
            val file = getInnerFile(fileName)
            if(!file.exists()){
                return null
            }
            val byteArray = readAsByte(file)
            val bitmapPainter = BitmapFactory.decodeByteArray(byteArray, 0, byteArray!!.size).asImageBitmap()
            return BitmapPainter(bitmapPainter)
        }
    }

}